package api

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
	"learning.com/edu/models"
	"learning.com/edu/utils/validator"
)

/*
 * 获取课程评价列表
 */
func (api *Api) getCourseReviews(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseID int64
		FetchMyReview bool
		models.PageFilter
	}

	v := validator.New()
	qs := r.URL.Query()
	input.CourseID = api.h.ReadInt64(qs, "course_id", 0, v)
	input.FetchMyReview = api.h.ReadBool(qs, "fetch_my_review", false, v)
	input.PageFilter.Page = api.h.ReadInt(qs, "page", 1, v)
	input.PageFilter.PageSize = api.h.ReadInt(qs, "page_size", 20, v)

	v.Check(input.CourseID > 0, "course_id", "课程 ID 为必填项")
	input.PageFilter.ValidateFilters(v)
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	reviews, meta, err := api.models.Business.GetCourseReviews(input.CourseID, 
		&input.PageFilter)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	var myReview *models.CourseReview
	if input.FetchMyReview {
		user := api.middleware.ContextGetUser(r)
		myReview, err = api.models.Business.GetCourseReview(input.CourseID, user.ID)
		if err != nil {
			api.h.ServerErrorResponse(w, r, err)
			return
		}
	}
	
	data := map[string]interface{}{
		"reviews": reviews,
		"page_meta": meta,
		"my_review": myReview,
	}
	resp := api.h.NewResponse(0, data)
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 创建课程评价
 */
func (api *Api) writeCourseReview(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseID int64 `json:"course_id"`
		Rating int `json:"rating"`
		Content string `json:"content"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(input.CourseID > 0, "course_id", "course id is required")
	v.Check(input.Content != "", "content", "content is required")
	v.Check(input.Rating >= 1 && input.Rating <= 5, "rating", "rating must be between 1 and 5")
	v.Check(len(input.Content) <= 500, "content", "content must be less than 500 characters")

	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	review, err := api.models.Business.WriteCourseReview(user.ID, input.CourseID, 
		input.Rating, input.Content)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	data := map[string]interface{}{
		"my_review": review,
	}

	resp := api.h.NewResponse(0, data)
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 回复课程评价
 */
func (api *Api) replyCourseReview(w http.ResponseWriter, r *http.Request) { 
	var input struct {
		CourseID int64 `json:"course_id"`
		ReviewID int64 `json:"review_id"`
		Content string `json:"content"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(input.CourseID > 0, "course_id", "course id is required")
	v.Check(input.ReviewID > 0, "review_id", "review id is required")
	v.Check(input.Content != "", "content", "content is required")
	v.Check(len(input.Content) <= 500, "content", "content must be less than 500 characters")

	authorId, err := api.models.Courses.GetCourseAutherId(input.CourseID)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	user := api.middleware.ContextGetUser(r)
	v.Check(user.ID == authorId, "user", "用户不是该课程的作者")

	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	err = api.models.Business.ReplyCourseReview(input.ReviewID, input.Content)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	resp := api.h.NewResponse(0, map[string]interface{}{})
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 添加课程到收藏夹
 */
func (api *Api) AddToFavoriteCourse(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseID int64 `json:"course_id"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(input.CourseID > 0, "course_id", "课程ID为必填项")
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	err = api.models.Business.AddToFavoriteCourse(user.ID, input.CourseID)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	resp := api.h.NewResponse(0, map[string]interface{}{})
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 移除课程收藏夹
 */
func (api *Api) RemoveFromFavoriteCourse(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseID int64 `json:"course_id"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(input.CourseID > 0, "course_id", "课程ID为必填项")
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	err = api.models.Business.RemoveFromFavoriteCourse(user.ID, input.CourseID)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	resp := api.h.NewResponse(0, map[string]interface{}{})
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 添加课程到购物车
 */
func (api *Api) AddCourseToShoppingCart(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseID int64 `json:"course_id"`
		Price float32 `json:"price"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(input.CourseID > 0, "course_id", "课程ID为必填项")
	v.Check(input.Price > 0, "price", "价格必须大于0")
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	err = api.models.Business.AddCourseToShoppingCart(user.ID, input.CourseID, 
		input.Price)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	resp := api.h.NewResponse(0, map[string]interface{}{})
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 移除购物车课程
 */
func (api *Api) RemoveCourseFromShoppingCart(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseIdArray []int64 `json:"course_id_array"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(len(input.CourseIdArray) > 0, "course_id", "课程ID为必填项")
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	total, err := api.models.Business.RemoveCourseFromShoppingCart(user.ID, input.CourseIdArray)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	data := map[string]interface{}{
		"total_price": total,
	}
	resp := api.h.NewResponse(0, data)
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 购买课程
 */
func (api *Api) PurchaseCourse(w http.ResponseWriter, r *http.Request) {
	var input struct {
		CourseIdArray []int64 `json:"course_id_array"`
	}

	err := api.h.ReadJSON(w, r, &input)
	if err != nil {
		api.h.BadRequestResponse(w, r, err)
		return
	}

	v := validator.New()
	v.Check(len(input.CourseIdArray) > 0, "course_id", "课程ID为必填项")
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	total, err := api.models.Business.PurchaseCourse(user.ID, input.CourseIdArray)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	data := map[string]interface{}{
		"total_price": total,
	}
	resp := api.h.NewResponse(0, data)
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 获取课程订单
 */
func (api *Api) getCourseOrders(w http.ResponseWriter, r *http.Request) {
	var input struct {
		ids []int64
	}
	
	v := validator.New()
	qs := r.URL.Query()
	input.ids = api.h.ReadInt64Slice(qs, "course_ids", v)
	v.Check(len(input.ids) > 0, "course_ids", "课程ID为必填项")
	if !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	courseOrders, err := api.models.Business.GetCourseOrderInInArray(input.ids, user.ID)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	data := map[string]interface{}{
		"orders": courseOrders,
	}
	resp := api.h.NewResponse(0, data)
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

/*
 * 获取正在购买的课程
 */
func (api *Api) getPurchasingCourse(w http.ResponseWriter, r *http.Request) {
	var input struct {
		models.PageFilter
	}

	v := validator.New()
	qs := r.URL.Query()
	input.PageFilter.Offset = api.h.ReadInt(qs, "offset", 0, v)
	input.PageFilter.Page = api.h.ReadInt(qs, "page", 1, v)
	input.PageFilter.PageSize = api.h.ReadInt(qs, "page_size", 20, v)
	
	if input.PageFilter.ValidateFilters(v); !v.Valid() {
		api.h.FailedValidationResponse(w, r, v.Errors)
		return
	}

	user := api.middleware.ContextGetUser(r)
	orders, meta, err := api.models.Business.GetPurchasingCourses(user.ID, &input.PageFilter)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
		return
	}

	var totalPrice float32 = 0
	if len(orders) > 0 {
		totalPrice = orders[0].TotalPrice
	}

	data := map[string]interface{}{
		"orders": orders,
		"page_meta": meta,
		"total_price": totalPrice,
	}

	resp := api.h.NewResponse(0, data)
	err = api.h.WriteJSON(w, http.StatusOK, resp, nil)
	if err != nil {
		api.h.ServerErrorResponse(w, r, err)
	}
}

func (api *Api) businessRoutes(router *httprouter.Router) {
	// 课程评价
	router.HandlerFunc(http.MethodGet, "/v1/course/reviews", api.getCourseReviews)
	// 创建课程评价
	router.HandlerFunc(http.MethodPost, "/v1/course/review", 
		api.middleware.RequireAuthenticatedUser(api.writeCourseReview))
	// 回复课程评价
	router.HandlerFunc(http.MethodPost, "/v1/course/review/reply", 
		api.middleware.RequireAuthenticatedUser(api.replyCourseReview))
	// 添加课程到收藏夹
	router.HandlerFunc(http.MethodPost, "/v1/course/favorite", 
		api.middleware.RequireAuthenticatedUser(api.AddToFavoriteCourse))
	// 移除课程收藏夹
	router.HandlerFunc(http.MethodDelete, "/v1/course/favorite", 
		api.middleware.RequireAuthenticatedUser(api.RemoveFromFavoriteCourse))
	// 添加课程到购物车
	router.HandlerFunc(http.MethodPost, "/v1/course/shopping_cart", 
		api.middleware.RequireAuthenticatedUser(api.AddCourseToShoppingCart))
	// 移除购物车课程
	router.HandlerFunc(http.MethodDelete, "/v1/course/shopping_cart", 
		api.middleware.RequireAuthenticatedUser(api.RemoveCourseFromShoppingCart))
	// 购买课程
	router.HandlerFunc(http.MethodPost, "/v1/course/order", 
		api.middleware.RequireAuthenticatedUser(api.PurchaseCourse))
	// 获取课程订单
	router.HandlerFunc(http.MethodGet, "/v1/course/orders", 
		api.middleware.RequireAuthenticatedUser(api.getCourseOrders))
	// 获取正在购买的课程
	router.HandlerFunc(http.MethodGet, "/v1/course/purchasing", 
		api.middleware.RequireAuthenticatedUser(api.getPurchasingCourse))
}